import { cadAppLog, cadAppWarnLog, CMEVENTS, ExtensionID } from '@amcax/base';
import { Renderer3D, RendererMgr } from '@amcax/renderer';
import { PRODUCT_EVENT } from '@app-cad/common/Constants';
import {
  CoreBasicCommands,
  ctx2,
  dataManager,
  docMgr,
  referenceManager,
  userEvents,
} from '@app-cad/module';
import { wsApi } from '../server/wsApi';

export class CmdManager {
  private _undo: number = 0;
  private _redo: number = 0;

  get canUndo(): boolean {
    return this._undo > 0;
  }

  get canRedo(): boolean {
    return this._redo > 0;
  }

  async updateUndoSize() {
    const { undo, redo } = (await wsApi.getUndoSize()) as any;
    cadAppLog('updateUndoSize', undo, redo);
    this._undo = undo;
    this._redo = redo;
    userEvents.emit(CMEVENTS.CMD_MGR_EXECUTED, this);
  }

  increaseUndo(): void {
    // this._undo++;
    // userEvents.emit(CMEVENTS.CMD_MGR_EXECUTED, this);
  }

  async undo() {
    if (!this.canUndo) {
      cadAppWarnLog('no more undo command');
      return;
    }
    cadAppLog('execute undo !!!!');

    if (docMgr.getCurrentSketchDxid()) {
      await wsApi.undo('SKETCHER');
    } else {
      await wsApi.undo();
    }

    userEvents.emit(PRODUCT_EVENT.UPDATE_CONSTRAINTS);
    // this.updateUndoSize();
  }

  async redo() {
    if (!this.canRedo) {
      cadAppWarnLog('no more redo command');
      return;
    }
    cadAppLog('execute redo !!!!');
    if (docMgr.getCurrentSketchDxid()) {
      await wsApi.redo('SKETCHER');
    } else {
      await wsApi.redo();
    }
    userEvents.emit(PRODUCT_EVENT.UPDATE_CONSTRAINTS);
    // this.updateUndoSize();
  }

  // 若某元素被隐藏，则初始化获取visualData时该元素会被略过
  // 因此编辑元素时，可能会遇到依赖的元素的visualData不存在的情况，需要按需获取
  async fetchDependentShapeInfo(pickIds: string[]) {
    const dxids = pickIds.filter((pickId) => {
      if (pickId == null) {
        return false;
      }

      if (pickId === 'ORIGIN') {
        return false;
      }

      if (referenceManager.basicReferencePlaneIDs.includes(pickId)) {
        return false;
      }

      const dxid = pickId.replace(/:.*$/, '');

      const documentObject = docMgr.getDocumentObjectById(dxid);

      if (documentObject == null) {
        return false;
      }

      const hasShapeInfo =
        dataManager.getShapeData(documentObject.shape) != null;

      return !dataManager.isReferenceObject(documentObject) && !hasShapeInfo;
    });

    if (dxids.length === 0) {
      return;
    }

    const modelDatas = await CoreBasicCommands.getVisualData(
      dxids,
      ExtensionID.CAD,
      false,
      true,
    );
    ctx2.viewer.sceneSetup.adjustCameraForVisualData(modelDatas);

    RendererMgr.getRender<Renderer3D>('3d').saveShapeDatas(modelDatas);
  }
}

export const cmdMgr = new CmdManager();
